package com.bonc.apicreator.swagger.action;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.bonc.apicreator.constant.BaseConstant;
import com.bonc.apicreator.dao.ApiDao;
import com.bonc.apicreator.dao.ApiRequestDao;
import com.bonc.apicreator.dao.ApiResponseDao;
import com.bonc.apicreator.dao.ProjectDao;
import com.bonc.apicreator.entity.Project;
import com.bonc.apicreator.entity.RestApi;
import com.bonc.apicreator.entity.RestApiRequest;
import com.bonc.apicreator.entity.RestApiResponse;
import com.bonc.apicreator.swagger.models.OperationForSort;
import com.bonc.apicreator.swagger.utils.BuildUtil;
import com.bonc.apicreator.utils.DocExportUtil;

import io.swagger.config.SwaggerConfig;
import io.swagger.models.Info;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.Tag;


/**
 * swaggerConfig
 *
 * @author liuchang
 * @version 2016年8月21日
 * @see SwaggerConfig
 * @since
 */
@Component
public class SwaggerAction {
    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerAction.class);

    /**
     * projectDao
     */
    @Autowired
    private ProjectDao projectDao;

    /**
     * ApiDao
     */
    @Autowired
    private ApiDao apiDao;

    /**
     * ApiResponseDao
     */
    @Autowired
    private ApiResponseDao responseDao;

    /**
     * ApiRequestDao
     */
    @Autowired
    private ApiRequestDao requestDao;

    /**
     * Description:创建所有信息
     * 
     * @param proId
     * @return Swagger
     * @see
     */
    public Swagger buildApi(Long proId) {

        Swagger swagger = new Swagger();
        Project project = projectDao.findOne(proId);
        // 获取API接口信息
        List<RestApi> apis = apiDao.findByProIdOrderBySort(proId);

        if (apis.size() == 0) {
            return swagger;
        }

        createApiInfo(swagger, project, apis);
        createTags(swagger, apis);
        /*
         * for(RestApi api:apis) { createModel(swagger, api); }
         */
        createPath(swagger, apis, proId);
        return swagger;

    }

    /**
     * Description:创建接口标签
     * 
     * @param swagger
     * @param apis
     *            void
     * @see
     */
    public void createTags(Swagger swagger, List<RestApi> apis) {
        List<Tag> tagList = new ArrayList<Tag>();
        Tag tag = null;
        //swagger的标签
        for (int i = 0; i < apis.size(); i++ ) {
            tag = new Tag();

            tagList.add(tag);
        }

        swagger.setTags(tagList);
    }

    /**
     * api接口信息
     */
    private void createApiInfo(Swagger swagger, Project project, List<RestApi> apis) {

        String rootUrl = project.getRootUrl();
        //设置项目根路径
        if (StringUtils.isEmpty(rootUrl)) {
            rootUrl = "";
        }
        else {
            if (rootUrl.contains("http://") || rootUrl.contains("https://")) {
                rootUrl = rootUrl.replace("http://", "").replace("https://", "");
            }
        }
        //设置主机地址
        swagger.setHost(rootUrl);
        //swagger页面显示的基路径
        swagger.setBasePath("/");
        //设置swagger的基本信息
        Info info = new Info();
        info.setDescription(project.getDescription());
        info.setTitle(project.getName());
        info.setVersion(project.getVersion());

        swagger.setInfo(info);

    }

    /**
     * Description:创建方法
     * 
     * @param swagger
     * @param apis
     * @param proId
     *            void
     * @see
     */
    private void createPath(Swagger swagger, List<RestApi> apis, Long proId) {
        LinkedHashMap<String, Path> pathMap = new LinkedHashMap<String, Path>();
        Path path = null;
        OperationForSort operation = null;
        for (RestApi api : apis) {
            List<RestApiRequest> apiRequests = requestDao.findByApiIdOrderByDataTypeDesc(api.getId());
            List<RestApiResponse> apiResponses = responseDao.findByApiId(api.getId());
            for (RestApiResponse response : apiResponses) {
            	//构建response节点树
                buildResponseTreeNode(response);

            }
            //组装api信息
            operation = BuildUtil.buildOperation(api, apiRequests, apiResponses);
            //设置路径
            path = BuildUtil.buildPath(pathMap.get(api.getRequestUrl()), api, operation);
            pathMap.put(api.getRequestUrl(), path);

        }
        swagger.setPaths(pathMap);
    }

    /**
     * Description: 构建response节点树
     * 
     * @param response
     *            void
     * @see
     */
    private void buildResponseTreeNode(RestApiResponse response) {
        if (response == null) {
            return;
        }
        if (BaseConstant.TYPE_OBJECT.equals(response.getType())
            || BaseConstant.TYPE_ARRAY.equals(response.getType())) {
            List<RestApiResponse> apiResponses = responseDao.findByTopIdOrderByNodeIdAsc(
                response.getId());
            if (!CollectionUtils.isEmpty(apiResponses)) {
                for (RestApiResponse sub : apiResponses) {
                    buildResponseTreeNode(sub);
                }
            }
            response.setChildren(apiResponses);

        }
    }

    /**
     * Description: 创建非json数据
     * 
     * @param project
     * @return Map<String,Object>
     * @see
     */
    public Map<String, Object> buildDocTmplData(Project project) {
        Map<String, Object> tmplData = new HashMap<>();
        if (project == null) {
            return tmplData;
        }

        // 组装基本信息
        buildBasicInfoTmplData(tmplData, project);

        // 组装接口信息
        buildInterTmplData(tmplData, project.getId());

        return tmplData;
    }

    /**
     * Description: 组装基本信息
     * 
     * @param tmplData
     * @param project
     *            void
     * @see
     */
    private void buildBasicInfoTmplData(Map<String, Object> tmplData, Project project) {
        Map<String, Object> basicInfo = new HashMap<>();
        basicInfo.put("title", project.getName());
        basicInfo.put("version", project.getVersion());
        basicInfo.put("description", project.getDescription());
        basicInfo.put("host", project.getRootUrl());
        basicInfo.put("basePath", project.getContext());

        tmplData.put("basicInfo", basicInfo);
    }

    /**
     * Description:组装接口信息
     * 
     * @param tmplData
     * @param proId
     *            void
     * @see
     */
    @SuppressWarnings("rawtypes")
    private void buildInterTmplData(Map<String, Object> tmplData, Long proId) {

        // 接口列表
        List<RestApi> interList = apiDao.findByProIdOrderBySort(proId);

        // 请求信息列表
        Map<Long, List<RestApiRequest>> paramInfoMap = getInterParamInfo(proId);

        // 响应信息列表
        Map<Long, List<RestApiResponse>> respInfoMap = getInterRespInfo(proId);

        // 接口模板数据
        Map<String, List<Map>> interTmplData = DocExportUtil.buildInterTmplData(interList,
            paramInfoMap, respInfoMap);

        tmplData.put("moduleMap", interTmplData);
    }

    /**
     * Description: 组装响应信息
     * 
     * @param proId
     * @return Map<Long,List<RestApiResponse>>
     * @see
     */
    private Map<Long, List<RestApiResponse>> getInterRespInfo(Long proId) {
        List<RestApiResponse> paramList = new ArrayList<>();
        List<RestApi> apiList = apiDao.findByProIdOrderBySort(proId);
        Map<Long, List<RestApiResponse>> result = new HashMap<>();
        for (RestApi restApi : apiList) {
            paramList.addAll(responseDao.findByApiId(restApi.getId()));
        }
        Long apiId = -1L;
        for (RestApiResponse restApiResponse : paramList) {
            apiId = restApiResponse.getApiId();
            if (result.containsKey(apiId)) {
                result.get(apiId).add(restApiResponse);
            }
            else {
                List<RestApiResponse> temp = new ArrayList<RestApiResponse>();
                temp.add(restApiResponse);
                result.put(apiId, temp);
            }
        }
        LOGGER.info("组装的响应信息" + JSON.toJSONString(result));
        return result;
    }

    /**
     * Description: 组装请求信息
     * 
     * @param proId
     * @return Map<Long,List<RestApiRequest>>
     * @see
     */
    private Map<Long, List<RestApiRequest>> getInterParamInfo(Long proId) {
        List<RestApiRequest> paramList = new ArrayList<>();
        List<RestApi> apiList = apiDao.findByProIdOrderBySort(proId);
        Map<Long, List<RestApiRequest>> result = new HashMap<>();
        for (RestApi restApi : apiList) {
            paramList.addAll(requestDao.findByApiIdOrderByDataTypeDesc(restApi.getId()));
        }
        Long apiId = -1L;
        for (RestApiRequest restApiRequest : paramList) {
            apiId = restApiRequest.getApiId();
            if (result.containsKey(apiId)) {
                result.get(apiId).add(restApiRequest);
            }
            else {
                List<RestApiRequest> temp = new ArrayList<RestApiRequest>();
                temp.add(restApiRequest);
                result.put(apiId, temp);
            }
        }
        LOGGER.info("组装的请求" + JSON.toJSONString(result));
        return result;
    }
}
